package com.example.score.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.score.dto.FiveRate;
import com.example.score.entity.*;
import com.example.score.entity.vo.AcademicLevelResult;
import com.example.score.mapper.*;
import com.example.score.utils.CalculateQuestionNumUtil;
import com.example.score.utils.HttpUtils;
import com.example.score.utils.constants.ScoreFiveRateConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ScoreDistributionService {
    private final StudentSubmitMapper studentSubmitMapper;
    private final ExamDetailMapper examDetailMapper;
    private final ClassInfoMapper classInfoMapper;
    private final QuestionInfoMapper questionInfoMapper;
    private final QuestionScoreMapper questionScoreMapper;
    private final SubmitStatisticsMapper submitStatisticsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${api.base-yj-url}")
    private String yjUrl;


    public List<Map<String, Object>> calculateScoreDistribution(Long examId, Long classId, Integer segment) {
        List<Map<String, Object>> distributions = new ArrayList<>();

        try {
            // 1. 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }

            // 2. 获取全部成绩数据
            List<StudentSubmit> allSubmits = studentSubmitMapper.selectByExamDetailId(examDetail.getId());

            // 3. 如果指定了班级，获取班级数据
            List<StudentSubmit> classSubmits = null;
            String className = null;
            if (classId != null && classId > 0) {
                ClassInfo classInfo = classInfoMapper.selectByExamDetailIdAndClassId(examDetail.getId(), classId);
                if (classInfo == null) {
                    throw new RuntimeException("未找到班级信息");
                }
                className = classInfo.getClassName();
                classSubmits = allSubmits.stream()
                    .filter(submit -> submit.getClassInfoId().equals(classInfo.getId()))
                    .collect(Collectors.toList());
            }

            // 4. 计算全部数据的分布
            Map<String, Object> totalData = new HashMap<>();
            totalData.put("type", "0");
            totalData.put("name", "全体");
            totalData.put("distributions", calculateDistributionForSubmits(allSubmits, examDetail.getFullScore(), segment, "全体"));
            // 计算统计数据
            if (!allSubmits.isEmpty()) {
                totalData.put("maxScore", CommonUtils.calculateMaxScore(allSubmits));
                totalData.put("minScore", CommonUtils.calculateMinScore(allSubmits));
                totalData.put("avgScore", String.format("%.2f",CommonUtils.calculateAverageScore(allSubmits)));
                totalData.put("stdDeviation", CommonUtils.calculateStandardDeviationForSubmits(allSubmits));
            } else {
                totalData.put("maxScore", 0.0);
                totalData.put("minScore", 0.0);
                totalData.put("avgScore", 0.0);
                totalData.put("stdDeviation", 0.0);
            }
            distributions.add(totalData);

            // 5. 如果有班级数据，计算班级数据的分布
            if (classSubmits != null) {
                Map<String, Object> classData = new HashMap<>();
                classData.put("type", "1");
                classData.put("name", className);
                classData.put("distributions", calculateDistributionForSubmits(classSubmits, examDetail.getFullScore(), segment, className));
                // 计算统计数据
                if (!allSubmits.isEmpty()) {
                    classData.put("maxScore", CommonUtils.calculateMaxScore(classSubmits));
                    classData.put("minScore", CommonUtils.calculateMinScore(classSubmits));
                    classData.put("avgScore", String.format("%.2f",CommonUtils.calculateAverageScore(classSubmits)));
                    classData.put("stdDeviation", CommonUtils.calculateStandardDeviationForSubmits(classSubmits));
                } else {
                    classData.put("maxScore", 0.0);
                    classData.put("minScore", 0.0);
                    classData.put("avgScore", 0.0);
                    classData.put("stdDeviation", 0.0);
                }
                distributions.add(classData);
            }

            return distributions;

        } catch (Exception e) {
            log.error("计算分数段分布失败", e);
            throw new RuntimeException("计算分数段分布失败: " + e.getMessage());
        }
    }

    private List<Map<String, Object>> calculateDistributionForSubmits(List<StudentSubmit> submits, int fullScore, int segment, String groupName) {
        List<Map<String, Object>> distributions = new ArrayList<>();
        int accumulatedCount = 0;

        for (int start = 0; start < fullScore; start += segment) {
            int end = Math.min(start + segment, fullScore);

            // 获取当前分数段的成绩
            int finalStart = start;
            List<StudentSubmit> rangeSubmits = submits.stream()
                    .filter(s -> {
                        double score = s.getScore();
                        // 关键逻辑：0分包含起始边界，其他情况排除起始边界
                        return (score == 0 && score >= finalStart) || (score != 0 && score > finalStart) && score <= end;
                    })
                    .collect(Collectors.toList());

            Map<String, Object> range = new HashMap<>();
            range.put("rangeStart", start);
            range.put("rangeEnd", end);
            range.put("currentCount", rangeSubmits.size());
            accumulatedCount += rangeSubmits.size();
            range.put("accumulatedCount", accumulatedCount);

            distributions.add(range);
        }

        return distributions;
    }

    public double[] calculateBoxPlotData(Long examId, Long classId) {
        try {
            // 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }

            // 获取成绩数据
            List<StudentSubmit> submits;
            if (classId != null && classId > 0) {
                ClassInfo classInfo = classInfoMapper.selectByExamDetailIdAndClassId(examDetail.getId(), classId);
                if (classInfo == null) {
                    throw new RuntimeException("未找到班级信息");
                }
                submits = studentSubmitMapper.selectByClassInfoId(classInfo.getExamDetailId(), classInfo.getId());
            } else {
                submits = studentSubmitMapper.selectByExamDetailId(examDetail.getId());
            }

            // 提取有效成绩并排序
            List<Double> scores = submits.stream()
                    .map(StudentSubmit::getScore)
                    .sorted()
                    .collect(Collectors.toList());

            if (scores.isEmpty()) {
                return new double[]{0, 0, 0, 0, 0, 0};
            }

            // 计算各个分位数
            double p5 = CommonUtils.calculatePercentile(scores, 5);
            double p25 = CommonUtils.calculatePercentile(scores, 25);
            double median = CommonUtils.calculatePercentile(scores, 50);
            double p75 = CommonUtils.calculatePercentile(scores, 75);
            double p95 = CommonUtils.calculatePercentile(scores, 95);

            // 返回箱线图所需的数据：[最小值, 5%, 25%, 中位数, 75%, 95%]
            return new double[]{
                    scores.get(0),  // 最小值
                    p5,            // 5%分位
                    p25,           // 25%分位
                    median,        // 中位数
                    p75,           // 75%分位
                    p95           // 95%分位
            };
        } catch (Exception e) {
            log.error("计算箱线图数据失败", e);
            throw new RuntimeException("计算箱线图数据失败: " + e.getMessage());
        }
    }

    /**
     * 空白率
     *
     * @param examId
     * @param classId
     * @return
     */
    public List<Map<String, Object>> calculateBlankRate(Long examId, Long classId) {
        try {
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }

            // 获取所有题目信息
            List<QuestionInfo> questions = questionInfoMapper.selectByExamDetailId(examDetail.getId());

            // 获取有效的学生提交记录
            List<StudentSubmit> submits = studentSubmitMapper.selectByExamAndClass(examDetail.getId(), classId)
                    .stream()
                    .filter(s -> s.getSubmitStatus() == 1)
                    .collect(Collectors.toList());

            // 获取所有提交ID
            List<Long> submitIds = submits.stream()
                    .map(StudentSubmit::getId)
                    .collect(Collectors.toList());

            // 批量获取所有题目得分
            Map<Long, List<QuestionScore>> questionScoresMap = new HashMap<>();
            if (!submitIds.isEmpty()) {
                List<QuestionScore> allScores = questionScoreMapper.selectByStudentSubmitIds(submitIds);
                questionScoresMap = allScores.stream()
                        .collect(Collectors.groupingBy(QuestionScore::getQuestionId));
            }

            List<Map<String, Object>> result = new ArrayList<>();

            // 按题目统计空白率
            for (QuestionInfo question : questions) {
                Map<String, Object> stat = new HashMap<>();
                if(!ObjectUtils.isEmpty(question.getQuestionAlias())){
                    stat.put("questionNum", question.getQuestionTypeName() + "-" + question.getQuestionAlias());
                }else {
                    int bigQuestionNum = CalculateQuestionNumUtil.bigQuestionNum(question.getQuestionNum());
                    int smallQuestionNum = CalculateQuestionNumUtil.smallQuestionNum(question.getQuestionNum());
                    if (smallQuestionNum != 0) {
                        stat.put("questionNum", bigQuestionNum + "-" + question.getQuestionTypeName() + "-" + smallQuestionNum);
                    } else {
                        stat.put("questionNum", question.getQuestionTypeName() + "-" + bigQuestionNum);
                    }
                }
                stat.put("questionId", question.getQuestionId());
                stat.put("score", question.getQuestionScore());
                stat.put("isSubjective", question.getIsSubjectiveItem());

                // 从Map中获取该题目的所有得分记录
                List<QuestionScore> scores = questionScoresMap.getOrDefault(question.getQuestionId(), Collections.emptyList());

                if (!scores.isEmpty()) {
                    // 计算空白率
                    long blankCount;
                    if (question.getIsSubjectiveItem() == 1) {
                        // 主观题：检查答案是否为空
                        blankCount = scores.stream()
                                .filter(s -> s.getStudentAnswer() == null || s.getStudentAnswer().trim().isEmpty())
                                .count();
                    } else {
                        // 客观题：检查得分是否为0
                        blankCount = scores.stream()
                                .filter(s -> Math.abs(s.getScore()) < 0.001)
                                .count();
                    }

                    double blankRate = (double) blankCount / scores.size() * 100;
                    stat.put("blankRate", CommonUtils.formatNumber(blankRate));
                } else {
                    stat.put("blankRate", "0.00");
                }

                result.add(stat);
            }

            return result;

        } catch (Exception e) {
            log.error("计算空白率分布失败", e);
            throw new RuntimeException("计算空白率分布失败: " + e.getMessage());
        }
    }


    /**
     * 两分五率
     *
     * @param examId
     * @param classId
     * @return
     */
    public List<Map<String, Object>> calculateScoreRates(Long examId, Long classId,Long teacherId) {
        try {
            // 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }

            List<StudentSubmit> examSubmits = studentSubmitMapper.selectByExamDetailId(examDetail.getId());
            // 获取学生提交记录
            List<StudentSubmit> classSubmits = null;
            String className = "";
            if (classId != null && classId > 0) {
                ClassInfo classInfo = classInfoMapper.selectByExamDetailIdAndClassId(examDetail.getId(), classId);
                if (classInfo == null) {
                    throw new RuntimeException("未找到班级信息");
                }
                className = classInfo.getClassName();
                classSubmits = examSubmits.stream()
                    .filter(examSubmit -> examSubmit.getClassInfoId().equals(classInfo.getId()))
                    .collect(Collectors.toList());
            }

            // 只统计有效提交
            examSubmits = examSubmits.stream()
                    .filter(s -> s.getSubmitStatus() == 1)
                    .collect(Collectors.toList());

            if (classSubmits != null) {
                classSubmits = classSubmits.stream()
                        .filter(s -> s.getSubmitStatus() == 1)
                        .collect(Collectors.toList());
            }

            // 加载每个提交的题目得分
            for (StudentSubmit submit : examSubmits) {
                List<QuestionScore> scores = questionScoreMapper.selectByStudentSubmitId(submit.getId());
                submit.setQuestionScores(scores);
            }

            if (classSubmits != null) {
                for (StudentSubmit submit : classSubmits) {
                    List<QuestionScore> scores = questionScoreMapper.selectByStudentSubmitId(submit.getId());
                    submit.setQuestionScores(scores);
                }
            }

            List<Map<String, Object>> result = new ArrayList<>();

            List<FiveRate> fiveRates = getFiveRates(examDetail.getSubjectOnlyid(), examDetail.getGradeId(), examDetail,teacherId);
            if(fiveRates.size() < 5) {
                throw new RuntimeException("五率百分比设置错误,请设置完成后查看分析");
            }
            // 计算全部数据
            Map<String, Object> totalStats = calculateStats(examSubmits, examDetail, fiveRates);
            totalStats.put("type", "0");
            totalStats.put("name", "全体");
            result.add(totalStats);

            // 如果有班级数据，计算班级数据
            if (classSubmits != null) {
                Map<String, Object> classStats = calculateStats(classSubmits, examDetail, fiveRates);
                classStats.put("type", "1");
                totalStats.put("name", className);
                result.add(classStats);
            }

            return result;
        } catch (Exception e) {
            log.error("计算成绩概览失败: {}", e.getMessage(), e);
            throw new RuntimeException("计算成绩概览失败: " + e.getMessage());
        }
    }

    @NotNull
    private List<FiveRate> getFiveRates(Long subjectId, Long gradeId, ExamDetail examDetail,Long teacherId) throws Exception {
        String response = null;
        List<FiveRate> fiveRates = new ArrayList<>();
        AcademicLevelResult academicLevelResult = null;
        // 获取老师存储的评级规则
        log.info("");
        String specialtyLevelPrefix = "SPECIALTYLEVEL_"+teacherId;
        Object o = redisTemplate.opsForValue().get(specialtyLevelPrefix);
        if(Objects.nonNull(o)){
                String jsonString = JSONObject.toJSONString(o);
                List<AcademicLevelResult.DataBean.AcademiclevelsBean> academiclevels = JSONArray.parseArray(jsonString, AcademicLevelResult.DataBean.AcademiclevelsBean.class);
                academicLevelResult = new AcademicLevelResult();
                AcademicLevelResult.DataBean data = new AcademicLevelResult.DataBean();
                data.setType(1);
                data.setAcademiclevels(academiclevels);
                academicLevelResult.setData(Arrays.asList(data));
        }else{
            String url = yjUrl + "/api/academiclevel/parameter";
            response = HttpUtils.sendGet(url, "subjectId=" + subjectId + "&gradeId=" + gradeId);
            try {
                academicLevelResult = JSON.parseObject(response, AcademicLevelResult.class);
            }catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }
        AcademicLevelResult.DataBean dataBean = academicLevelResult.getData().stream().filter(d-> d.getType() == 1).collect(Collectors.toList()).get(0);
        for(AcademicLevelResult.DataBean.AcademiclevelsBean academiclevelsBean: dataBean.getAcademiclevels()){
            FiveRate fiveRate = new FiveRate();
            if(academiclevelsBean.getName().equals(ScoreFiveRateConstants.FullScoreRate)) {
                fiveRate.setType(0);
            }else if(academiclevelsBean.getName().equals(ScoreFiveRateConstants.ExcellentScoreRate)) {
                fiveRate.setType(1);
            }else if (academiclevelsBean.getName().equals(ScoreFiveRateConstants.GoodScoreRate)) {
                fiveRate.setType(2);
            }else if (academiclevelsBean.getName().equals(ScoreFiveRateConstants.PassScoreRate)) {
                fiveRate.setType(3);
            }else {
                fiveRate.setType(4);
            }
            int fullScore = examDetail.getFullScore();
            Double startScore = fullScore * (academiclevelsBean.getStartScore()/100.0);
            Double endScore = fullScore * (academiclevelsBean.getEndScore()/100.0);
            //计算分数
            fiveRate.setStartScore(startScore);
            fiveRate.setEndScore(endScore);
            fiveRates.add(fiveRate);
        }
        return fiveRates;
    }

    private Map<String, Object> calculateStats(List<StudentSubmit> submits, ExamDetail examDetail, List<FiveRate> fiveRates) {
        Map<String, Object> stats = new HashMap<>();

        // 基础统计
        stats.put("submitCount", submits.size());
        stats.put("highestScore", CommonUtils.formatNumber(CommonUtils.calculateMaxScore(submits)));
        stats.put("lowestScore", CommonUtils.formatNumber(CommonUtils.calculateMinScore(submits)));

        // 平均分统计
        stats.put("objectiveAvg", CommonUtils.formatNumber(CommonUtils.calculateObjectiveAverage(submits)));
        stats.put("subjectiveAvg", CommonUtils.formatNumber(CommonUtils.calculateSubjectiveAverage(submits)));
        stats.put("totalAvg", CommonUtils.formatNumber(CommonUtils.calculateAverageScore(submits)));

        // 标准差统计
        stats.put("objectiveStd", CommonUtils.formatNumber(CommonUtils.calculateObjectiveStdDev(submits)));
        stats.put("subjectiveStd", CommonUtils.formatNumber(CommonUtils.calculateSubjectiveStdDev(submits)));
        stats.put("totalStd", CommonUtils.formatNumber(CommonUtils.calculateStandardDeviationForSubmits(submits)));

        // 分数段统计
        int fullScoreCount = CommonUtils.countFullScore(submits, fiveRates);
        int excellentCount = CommonUtils.countExcellent(submits, fiveRates);
        int goodCount = CommonUtils.countGood(submits, fiveRates);
        int passCount = CommonUtils.countPass(submits, fiveRates);
        int lowCount = CommonUtils.countLow(submits, fiveRates);

        //满分
        stats.put("fullScoreCount", fullScoreCount);
        stats.put("fullScoreRate", CommonUtils.formatRate(fullScoreCount, submits.size()));
        //优秀
        stats.put("excellentCount", excellentCount);
        stats.put("excellentRate", CommonUtils.formatRate(excellentCount, submits.size()));
        //良好
        stats.put("goodCount", goodCount);
        stats.put("goodRate", CommonUtils.formatRate(goodCount, submits.size()));
        //及格
        stats.put("passCount", passCount);
        stats.put("passRate", CommonUtils.formatRate(passCount, submits.size()));
        //低分
        stats.put("lowCount", lowCount);
        stats.put("lowRate", CommonUtils.formatRate(lowCount, submits.size()));

        return stats;
    }

    public List<Map<String, Object>> calculateStudentDistribution(Long examId, Long classId) {
        try {
            // 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }

            // 获取所有学生提交记录
            List<StudentSubmit> examSubmits = studentSubmitMapper.selectByExamDetailId(examDetail.getId())
                    .stream()
                    .filter(s -> s.getSubmitStatus() == 1)
                    .collect(Collectors.toList());

            // 如果指定了班级，获取班级数据
            List<StudentSubmit> classSubmits = null;
            String className = null;
            if (classId != null && classId > 0) {
                ClassInfo classInfo = classInfoMapper.selectByExamDetailIdAndClassId(examDetail.getId(), classId);
                if (classInfo == null) {
                    throw new RuntimeException("未找到班级信息");
                }
                className = classInfo.getClassName();
                classSubmits = examSubmits.stream()
                    .filter(submit -> submit.getClassInfoId().equals(classInfo.getId()))
                    .collect(Collectors.toList());
            }

            List<Map<String, Object>> result = new ArrayList<>();
            double fullScore = examDetail.getFullScore();

            // 计算全部数据
            Map<String, Object> totalStats = calculateStudentStats(examSubmits, fullScore);
            totalStats.put("type", "0");
            totalStats.put("name", "全体");
            result.add(totalStats);

            // 如果有班级数据，计算班级数据
            if (classSubmits != null) {
                Map<String, Object> classStats = calculateStudentStats(classSubmits, fullScore);
                classStats.put("type", "1");
                classStats.put("name", className);
                // 获取学优生名单
                List<Map<String, Object>> excellentList = classSubmits.stream()
                    .filter(s -> (s.getScore() / fullScore) > 0.85)
                    .map(s -> {
                        Map<String, Object> student = new HashMap<>();
                        student.put("studentName", s.getStudentName());
                        student.put("studentNum", s.getStudentNum());
                        student.put("score", s.getScore());
                        return student;
                    })
                    .collect(Collectors.toList());
                classStats.put("excellentList", excellentList);

                // 获取学困生名单
                List<Map<String, Object>> poorList = classSubmits.stream()
                    .filter(s -> (s.getScore() / fullScore) < 0.40)
                    .map(s -> {
                        Map<String, Object> student = new HashMap<>();
                        student.put("studentName", s.getStudentName());
                        student.put("studentNum", s.getStudentNum());
                        student.put("score", s.getScore());
                        return student;
                    })
                    .collect(Collectors.toList());
                classStats.put("poorList", poorList);

                result.add(classStats);
            }

            return result;
        } catch (Exception e) {
            log.error("计算学生分布失败", e);
            throw new RuntimeException("计算学生分布失败: " + e.getMessage());
        }
    }

    private Map<String, Object> calculateStudentStats(List<StudentSubmit> submits, double fullScore) {
        Map<String, Object> stats = new HashMap<>();

        // 学优生：得分率超过85%
        List<StudentSubmit> excellentStudents = submits.stream()
                .filter(s -> (s.getScore() / fullScore) > 0.85)
                .collect(Collectors.toList());

        // 学困生：得分率低于40%
        List<StudentSubmit> poorStudents = submits.stream()
                .filter(s -> (s.getScore() / fullScore) < 0.40)
                .collect(Collectors.toList());

        // 计算学优生统计
        stats.put("excellentCount", excellentStudents.size());
        stats.put("excellentRate", CommonUtils.formatRate(excellentStudents.size(), submits.size()));
        stats.put("excellentAvg", CommonUtils.formatNumber(CommonUtils.calculateAverageScore(excellentStudents)));

        // 计算学困生统计
        stats.put("poorCount", poorStudents.size());
        stats.put("poorRate", CommonUtils.formatRate(poorStudents.size(), submits.size()));
        stats.put("poorAvg", CommonUtils.formatNumber(CommonUtils.calculateAverageScore(poorStudents)));

        return stats;
    }

    public List<Map<String, Object>> calculateGradeScoreDistribution(Long examId, Integer segment, List<Long> classIds) {
        List<Map<String, Object>> distributions = new ArrayList<>();

        try {
            // 1. 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }

            // 2. 获取全部成绩数据
            List<StudentSubmit> allSubmits = studentSubmitMapper.selectByExamDetailId(examDetail.getId());
            // 4. 计算全部数据的分布
            Map<String, Object> totalData = new HashMap<>();
            totalData.put("type", "0");
            totalData.put("name", "全体");
            totalData.put("distributions", calculateDistributionForSubmits(allSubmits, examDetail.getFullScore(), segment, "全体"));
            // 计算统计数据
            if (!allSubmits.isEmpty()) {
                totalData.put("maxScore", CommonUtils.calculateMaxScore(allSubmits));
                totalData.put("minScore", CommonUtils.calculateMinScore(allSubmits));
                totalData.put("avgScore", String.format("%.2f",CommonUtils.calculateAverageScore(allSubmits)));
                totalData.put("stdDeviation", CommonUtils.calculateStandardDeviationForSubmits(allSubmits));
            } else {
                totalData.put("maxScore", 0.0);
                totalData.put("minScore", 0.0);
                totalData.put("avgScore", 0.0);
                totalData.put("stdDeviation", 0.0);
            }
            distributions.add(totalData);
            if(ObjectUtils.isEmpty(classIds)) {
                classIds = allSubmits.stream().map(StudentSubmit::getClassId).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
            }
            List<ClassInfo> classInfos = classInfoMapper.selectByClassIds(classIds);
            List<Long> finalClassIds = classIds;
            Map<Long, List<StudentSubmit>> classMaps = allSubmits.stream().filter(s-> finalClassIds.contains(s.getClassId())).collect(Collectors.groupingBy(StudentSubmit::getClassId));
            // 5. 如果有班级数据，计算班级数据的分布
            classMaps.forEach((key, value) -> {
                Optional<ClassInfo> optionalValue = classInfos.stream().filter(c-> c.getClassId().equals(key)).findFirst();
                String className = optionalValue.map(ClassInfo::getClassName).orElse("");
                Map<String, Object> classData = new HashMap<>();
                classData.put("type", "1");
                classData.put("name", className);
                classData.put("distributions", calculateDistributionForSubmits(value, examDetail.getFullScore(), segment, className));
                // 计算统计数据
                if (!allSubmits.isEmpty()) {
                    classData.put("maxScore", CommonUtils.calculateMaxScore(value));
                    classData.put("minScore", CommonUtils.calculateMinScore(value));
                    classData.put("avgScore", String.format("%.2f",CommonUtils.calculateAverageScore(value)));
                    classData.put("stdDeviation", CommonUtils.calculateStandardDeviationForSubmits(value));
                } else {
                    classData.put("maxScore", 0.0);
                    classData.put("minScore", 0.0);
                    classData.put("avgScore", 0.0);
                    classData.put("stdDeviation", 0.0);
                }
                distributions.add(classData);
            });
            return distributions;

        } catch (Exception e) {
            log.error("计算分数段分布失败", e);
            throw new RuntimeException("计算分数段分布失败: " + e.getMessage());
        }
    }



    /**
     * 年级两分五率
     *
     * @param examId
     * @param classIds
     * @param gradeId
     * @param subjectId
     * @return
     */
    public List<Map<String, Object>> calculateGradeScoreRates(Long examId, List<Long> classIds, Long gradeId, Long subjectId) {
        try {
            // 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }
            List<StudentSubmit> examSubmits = studentSubmitMapper.selectByExamDetailId(examDetail.getId());
            // 只统计有效提交
            examSubmits = examSubmits.stream()
                    .filter(s -> s.getSubmitStatus() == 1)
                    .collect(Collectors.toList());
            // 加载每个提交的题目得分
            List<Long> studentSubmitIds = examSubmits.stream().map(StudentSubmit::getId).collect(Collectors.toList());
            List<QuestionScore> questionScores = questionScoreMapper.selectListBySubmitIds(studentSubmitIds);
            List<Long> questionIds = questionScores.stream().map(QuestionScore::getQuestionId).collect(Collectors.toList());
            List<QuestionInfo> questionInfos = questionInfoMapper.selectListByQuestionIds(questionIds);
            List<FiveRate> fiveRates = getFiveRates(subjectId, gradeId, examDetail,null);
            for (StudentSubmit submit : examSubmits) {
                List<QuestionScore> scores = questionScores.stream().filter(s-> s.getStudentSubmitId().equals(submit.getId())).collect(Collectors.toList());
                scores.forEach(questionScore -> {
                    QuestionInfo questionInfo = questionInfos.stream().filter(q-> q.getQuestionId().equals(questionScore.getQuestionId())).findFirst().orElse(null);
                    questionScore.setIsSubjectiveItem(questionInfo.getIsSubjectiveItem());
                    questionScore.setQuestionScore(questionScore.getQuestionScore());
                });
                submit.setQuestionScores(scores);
            }
            List<Map<String, Object>> result = new ArrayList<>();
            // 计算全部数据
            Map<String, Object> totalStats = calculateStats(examSubmits, examDetail, fiveRates);
            totalStats.put("type", "0");
            totalStats.put("name", "全体");
            totalStats.put("fullScoreRateRank", "-");
            totalStats.put("excellentRateRank", "-");
            totalStats.put("goodRateRank", "-");
            totalStats.put("passRateRank", "-");
            totalStats.put("lowRateRank", "-");
            result.add(totalStats);

            //按照班级分组
            if(ObjectUtils.isEmpty(classIds)) {
                classIds = examSubmits.stream().map(StudentSubmit::getClassId).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
            }
            List<ClassInfo> classInfos = classInfoMapper.selectByClassIds(classIds);
            List<Long> finalClassIds = classIds;
            Map<Long, List<StudentSubmit>> classMaps = examSubmits.stream().filter(s-> finalClassIds.contains(s.getClassId())).collect(Collectors.groupingBy(StudentSubmit::getClassId));

            // 存储班级统计结果，用于计算排名
            List<Map<String, Object>> classStatsList = new ArrayList<>();

            // 计算每个班级的统计数据
            classMaps.forEach((key, value) -> {
                Optional<ClassInfo> optionalValue = classInfos.stream().filter(c-> c.getClassId().equals(key)).findFirst();
                String className = optionalValue.map(ClassInfo::getClassName).orElse("");
                for (StudentSubmit submit : value) {
                    List<QuestionScore> scores = questionScores.stream().filter(s-> s.getStudentSubmitId().equals(submit.getId())).collect(Collectors.toList());
                    submit.setQuestionScores(scores);
                }
                Map<String, Object> classStats = calculateStats(value, examDetail, fiveRates);
                classStats.put("type", "1");
                classStats.put("name", className);
                classStatsList.add(classStats);
            });
            // 计算五率的排名
            String[] rateTypes = {"fullScoreRate", "excellentRate", "goodRate", "passRate", "lowRate"};
            for (String rateType : rateTypes) {
                // 按照比率从高到低排序（低分率除外）
                final boolean isAscending = rateType.equals("lowRate");
                classStatsList.sort((a, b) -> {
                    String rateA = (String) a.get(rateType);
                    String rateB = (String) b.get(rateType);
                    double valueA = Double.parseDouble(rateA.replace("%", ""));
                    double valueB = Double.parseDouble(rateB.replace("%", ""));
                    return isAscending ? Double.compare(valueA, valueB) : Double.compare(valueB, valueA);
                });

                // 计算排名（处理同率情况）
                int currentRank = 1;
                double lastRate = -1;
                for (int i = 0; i < classStatsList.size(); i++) {
                    Map<String, Object> classStats = classStatsList.get(i);
                    String rateStr = (String) classStats.get(rateType);
                    double currentRate = Double.parseDouble(rateStr.replace("%", ""));

                    if (i > 0 && currentRate == lastRate) {
                        // 如果与前一个比率相同，使用相同的排名
                        classStats.put(rateType + "Rank", currentRank);
                    } else {
                        // 如果与前一个比率不同，使用新的排名
                        currentRank = i + 1;
                        classStats.put(rateType + "Rank", currentRank);
                    }
                    lastRate = currentRate;
                }
            }

            // 将班级结果添加到最终结果中
            result.addAll(classStatsList);
            return result;
        } catch (Exception e) {
            log.error("计算成绩概览失败: {}", e.getMessage(), e);
            throw new RuntimeException("计算成绩概览失败: " + e.getMessage());
        }
    }

    /**
     * 年级提交率/空白率对比
     *
     * @param examId
     * @param classIds
     * @return
     */
    public List<Map<String, Object>> calculateGradeStudentSubmits(Long examId, List<Long> classIds) {
        try {
            List<Map<String, Object>> result = new ArrayList<>();
            // 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }
            List<SubmitStatistics> examSubmits = submitStatisticsMapper.selectByExamDetailId(examDetail.getId());
            if(examSubmits.isEmpty()) {
                throw new RuntimeException("未找到提交信息");
            }
            // 计算全部数据
            Map<String, Object> totalStats = calculateSubmitStats(examSubmits, "全体");
            result.add(totalStats);
            //按照班级分组
            if(ObjectUtils.isEmpty(classIds)) {
                classIds = examSubmits.stream().map(SubmitStatistics::getClassId).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
            }
            List<ClassInfo> classInfos = classInfoMapper.selectByClassIds(classIds);
            List<Long> finalClassIds = classIds;
            Map<Long, List<SubmitStatistics>> classMaps = examSubmits.stream().filter(s-> finalClassIds.contains(s.getClassId())).collect(Collectors.groupingBy(SubmitStatistics::getClassId));
            classMaps.forEach((key, value) -> {
                Optional<ClassInfo> optionalValue = classInfos.stream().filter(c-> c.getClassId().equals(key)).findFirst();
                String className = optionalValue.map(ClassInfo::getClassName).orElse("");
                Map<String, Object> classStats = calculateSubmitStats(value, className);
                result.add(classStats);
            });
            return result;
        } catch (Exception e) {
            log.error("计算成绩提交率失败: {}", e.getMessage(), e);
            throw new RuntimeException("计算成绩提交率失败: " + e.getMessage());
        }
    }

    private Map<String, Object> calculateSubmitStats(List<SubmitStatistics> examSubmits, String name) {
        Map<String, Object> map = new HashMap<>();
        //计算全体提交
        int submitNum = examSubmits.stream().mapToInt(SubmitStatistics::getSubmitStudents).sum();
        //总人数
        int totalSubmitNum = examSubmits.stream().mapToInt(SubmitStatistics::getTotalStudents).sum();
        double submitRate = BigDecimal.valueOf((double) submitNum / totalSubmitNum * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        map.put("submitRate", submitRate);
        map.put("name", name);
        map.put("totalSubmitNum", totalSubmitNum);
        map.put("submitNum", submitNum);
        return map;
    }

    public List<Map<String, Object>> calculateGradeStudentDistribution(Long examId, List<Long> classIds) {
        try {
            // 获取考试详情
            ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
            if (examDetail == null) {
                throw new RuntimeException("未找到考试详情");
            }
            // 获取所有学生提交记录
            List<StudentSubmit> examSubmits = studentSubmitMapper.selectByExamDetailId(examDetail.getId())
                    .stream()
                    .filter(s -> s.getSubmitStatus() == 1)
                    .collect(Collectors.toList());
            // 如果指定了班级，获取班级数据
            List<Map<String, Object>> result = new ArrayList<>();
            double fullScore = examDetail.getFullScore();
            // 计算全部数据
            Map<String, Object> totalStats = calculateStudentStats(examSubmits, fullScore);
            totalStats.put("type", "0");
            totalStats.put("name", "全体");
            result.add(totalStats);
            if(ObjectUtils.isEmpty(classIds)) {
                classIds = examSubmits.stream().map(StudentSubmit::getClassId).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
            }
            List<ClassInfo> classInfos = classInfoMapper.selectByClassIds(classIds);
            List<Long> finalClassIds = classIds;
            Map<Long, List<StudentSubmit>> classMaps = examSubmits.stream().filter(s-> finalClassIds.contains(s.getClassId())).collect(Collectors.groupingBy(StudentSubmit::getClassId));
            // 如果有班级数据，计算班级数据
            classMaps.forEach((key, value) -> {
                Optional<ClassInfo> optionalValue = classInfos.stream().filter(c-> c.getClassId().equals(key)).findFirst();
                String className = optionalValue.map(ClassInfo::getClassName).orElse("");
                if (value != null) {
                    Map<String, Object> classStats = calculateStudentStats(value, fullScore);
                    classStats.put("type", "1");
                    classStats.put("name", className);
                    // 获取学优生名单
                    List<Map<String, Object>> excellentList = value.stream()
                            .filter(s -> (s.getScore() / fullScore) > 0.85)
                            .map(s -> {
                                Map<String, Object> student = new HashMap<>();
                                student.put("studentName", s.getStudentName());
                                student.put("studentNum", s.getStudentNum());
                                student.put("score", s.getScore());
                                return student;
                            })
                            .collect(Collectors.toList());
                    classStats.put("excellentList", excellentList);
                    // 获取学困生名单
                    List<Map<String, Object>> poorList = value.stream()
                            .filter(s -> (s.getScore() / fullScore) < 0.40)
                            .map(s -> {
                                Map<String, Object> student = new HashMap<>();
                                student.put("studentName", s.getStudentName());
                                student.put("studentNum", s.getStudentNum());
                                student.put("score", s.getScore());
                                return student;
                            })
                            .collect(Collectors.toList());
                    classStats.put("poorList", poorList);
                    result.add(classStats);
                }
            });
            return result;
        } catch (Exception e) {
            log.error("计算学生分布失败", e);
            throw new RuntimeException("计算学生分布失败: " + e.getMessage());
        }
    }


}
